﻿using System;
using System.Collections.Generic;
using System.Text;

namespace ASmile.Extend
{
    public static class TimeExtend
    {
        /// <summary>
        /// 将时间格式化成只有日期的形式输出
        /// </summary>
        /// <param name="src">要转换的时间</param>        
        /// <param name="addDay">增加的天数</param>
        /// <returns></returns>
        public static DateTime ToDate(this DateTime src, int addDay)
        {
            return Convert.ToDateTime(src.AddDays(addDay).Date.ToString("yyyy-MM-dd"));
        }
        /// <summary>
        /// 将时间格式化成只有日期的形式输出
        /// </summary>
        /// <param name="sourceDate">要转换的时间</param>
        /// <returns></returns>
        public static DateTime ToDate(this DateTime sourceDate)
        {
            return ToDate(sourceDate, 0);
        }
        /// <summary>
        /// 将指定格式的字符串转换为时间格式
        /// </summary>
        public static DateTime ToDateTime(this string timeStr, string format = "yyyyMMddHHmmss")
        {
            DateTime dt = DateTime.ParseExact(timeStr, format, System.Globalization.CultureInfo.CurrentCulture);
            return dt;
        }
        /// <summary>
        /// DateTime时间格式转换为Unix时间戳格式,从1970.1.1 到当前时间的毫秒
        /// </summary>
        /// <param name="time"> DateTime时间格式</param>
        /// <returns>Unix时间戳格式(毫秒)</returns>
        public static long ToTimestamp(this DateTime time)
        {
            DateTime startTime = new DateTime(1970, 1, 1);
            return (long)(time - startTime).TotalMilliseconds;
        }
        /// <summary>
        /// 将时间字符串转换为时间戳，时间格式必须为：yyyy-MM-dd HH:mm:ss
        /// </summary>
        public static long ToTimestamp(this string timeStr)
        {
            var dt = Convert.ToDateTime(timeStr);
            return ToTimestamp(dt);
        }
        /// <summary>
        /// 时间戳转换为时间
        /// </summary>
        /// <param name="timeStamp">1970.1.1 到当前时间的毫秒 </param>
        public static DateTime ToTime(this long timeStamp)
        {
            //DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            DateTime dtStart = new DateTime(1970, 1, 1);
            return dtStart.AddMilliseconds(timeStamp);
        }
        /// <summary>
        /// 根据日期获得星期，返回 日、一、二、三、四、五、六
        /// </summary>
        public static string ToChinaWeek(this DateTime dt)
        {
            string[] Day = new string[] { "日", "一", "二", "三", "四", "五", "六" };
            string week = Day[Convert.ToInt32(dt.DayOfWeek.ToString("d"))].ToString();
            return week;
        }
        /// <summary>
        /// 转换为时辰，凌晨，上午，中午，下午，晚上
        /// </summary>
        public static string ToTimeRemark(this TimeSpan ts)
        {
            if (ts.Hours >= 7 && ts.Hours < 12)
            {
                return "上午";
            }
            else if (ts.Hours >= 12 && ts.Hours < 13)
            {
                return "中午";
            }
            else if (ts.Hours >= 13 && ts.Hours < 18)
            {
                return "下午";
            }
            else if (ts.Hours >= 18 && ts.Hours < 23)
            {
                return "晚上";
            }
            else
            {
                return "凌晨";
            }
        }
        /// <summary>
        /// 是否时间格式
        /// </summary>
        public static bool IsDateTime(string timeStr)
        {
            return DateTime.TryParse(timeStr, out _);
        }
        /// <summary>
        /// 获取指定时间 月 的第一天日期
        /// </summary>
        public static DateTime ToFirstDay(this DateTime dt)
        {
            //当月第一天0时0分0秒：
            return dt.AddDays(1 - dt.Day).Date;
        }
        /// <summary>
        /// 获取指定时间 月 的最后一天日期
        /// </summary>
        public static DateTime ToLastDay(this DateTime dt)
        {
            //当月最后一天23时59分59秒：
            return dt.AddDays(1 - dt.Day).Date.AddMonths(1).AddSeconds(-1);
        }
        /// <summary>
        /// 获取指定时间周一的日期
        /// </summary>
        public static DateTime ToFirstWeek(this DateTime dt)
        {
            //当月第一天0时0分0秒：
            int cutDay = dt.DayOfWeek == DayOfWeek.Sunday ? 7 : (int)dt.DayOfWeek;
            return dt.AddDays(0 - cutDay).Date;
        }
        /// <summary>
        /// 获取日期的说明，如：前天、昨天、今天、明天、后天，非说明范围内返回空字符串
        /// </summary>
        public static string ToDateRemark(this DateTime dt)
        {
            var nowDate = DateTime.Now.Date;
            if (dt.Date == nowDate.AddDays(-2)) return $"{dt.Date} 前天";
            if (dt.Date == nowDate.AddDays(-1)) return $"{dt.Date} 昨天";
            if (dt.Date == nowDate) return "今天";
            if (dt.Date == nowDate.AddDays(1)) return $"{dt.Date} 明天";
            if (dt.Date == nowDate.AddDays(2)) return $"{dt.Date} 后天";
            return $"{dt.Date}";
        }
        /// <summary>
        /// 将时间转换为 hh:mm 格式字符串
        /// </summary>
        public static string ToHMStr(this TimeSpan ts)
        {
            return ts.ToString(@"hh\:mm");
        }
        /// <summary>
        /// 将指定日期与当前日期比较，得出年龄（按周岁算到天）
        /// </summary>
        /// <param name="birthday">生日日期</param>
        /// <returns>返回年龄数值</returns>
        public static int ToAge(this DateTime birthday)
        {
            int age = DateTime.Now.Year - birthday.Year;
            if (DateTime.Now.Month < birthday.Month && DateTime.Now.Day < birthday.Day)
            {
                age--;
            }
            return age;
        }
        /// <summary>
        /// 得到年龄字符串，比如：30岁，5月，12天
        /// </summary>
        /// <param name="birthday">生日日期</param>
        /// <returns>返回年龄数值</returns>
        public static string ToAgeStr(this DateTime birthday)
        {
            var now = DateTime.Now.Date;
            if (birthday.Date > now.Date) return "Null";

            int y = now.Year - birthday.Year;

            birthday = birthday.AddYears(y);

            int m = now.Month - birthday.Month;
            if (m < 0)
            {
                y--;
                m = 12 + now.Month - birthday.Month;
            }
            birthday = birthday.AddMonths(m);

            int d = (int)(now - birthday).TotalDays;

            if (d < 0)
            {
                m--;
                d = (now - birthday.AddMonths(-1)).Days;
            }

            string ageStr = "";
            if (y > 0)
            {
                ageStr = $"{y}岁";
            }
            if (m > 0)
            {
                ageStr += $"{m}月";
            }
            if (d > 0)
            {
                ageStr += $"{d}天";
            }

            return ageStr;
        }
        /// <summary>
        /// 根据生日获取周岁年龄值，并返回年龄单位（岁、月、天）
        /// </summary>
        public static bool ToAge(this DateTime birthday, out int age, out string outAgeUnit)
        {
            if (birthday.Date > DateTime.Now.Date)
            {
                age = -1;
                outAgeUnit = null;
                return false;
            }
            var nowDate = DateTime.Now.Date;
            birthday = birthday.Date;

            age = nowDate.Year - birthday.Year;
            if (age > 0)
            {
                if (nowDate.Month < birthday.Month && nowDate.Day < birthday.Day)
                {
                    age--;
                }

                outAgeUnit = "岁";
                return true;
            }

            age = (nowDate.Year - birthday.Year) * 12 + (nowDate.Month - birthday.Month);
            if (age > 0)
            {
                outAgeUnit = "月";
                return true;
            }
            age = (int)(nowDate - birthday).TotalDays;
            outAgeUnit = "天";
            return true;
        }
        /// <summary>
        /// 返回年龄字符串，如 18岁，8月，15天
        /// </summary>
        public static string ToAge2(this DateTime birthday)
        {
            if (!ToAge(birthday, out int age, out string ageUnit))
            {
                return "Err";
            }
            else
            {
                return $"{age}{ageUnit}";
            }
        }
        /// <summary>
        /// 返回年龄(岁)
        /// </summary>
        public static int ToAgeYear(this DateTime birthday)
        {
            ToAge(birthday, out int age, out string ageUnit);
            if (ageUnit != "岁") return 0;
            return age;
        }
        /// <summary>
        /// 将指定时间格式的 时 分 秒 转换为TimeSpan 格式 
        /// </summary>
        public static TimeSpan ToTimeSpan(this DateTime dt)
        {
            return new TimeSpan(dt.Hour, dt.Minute, dt.Second);
        }
        /// <summary>
        /// 转换为iso 8601 格式字符串
        /// </summary>
        public static string ToISO8601(this DateTime dt)
        {
            //string ISO8601time = DateTime.UtcNow.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:sszzzz");
            string ISO8601time2 = dt.ToString("yyyy-MM-ddTHH:mm:sszzzz");
            return ISO8601time2;
        }
    }
}
